//*******************************************************************       //
//IMPORTANT NOTICE                                                          //
//================                                                          //
//Copyright Mentor Graphics Corporation 1996 - 1999.  All rights reserved.  //
//This file and associated deliverables are the trade secrets,              //
//confidential information and copyrighted works of Mentor Graphics         //
//Corporation and its licensors and are subject to your license agreement   //
//with Mentor Graphics Corporation.                                         //
//                                                                          //
//Use of these deliverables for the purpose of making silicon from an IC    //
//design is limited to the terms and conditions of your license agreement   //
//with Mentor Graphics If you have further questions please contact Mentor  //
//Graphics Customer Support.                                                //
//                                                                          //
//This Mentor Graphics core (m8051w v2002.080) was extracted on             //
//workstation hostid 8316cbec Inventra                                      //
// Dual-port clocked RAM model for M8051W/EW internal data memory
// 
// $Log: cram.v,v $
// Revision 1.5  2001/11/20
// First checkin of version 2 features and name change
//
// Revision 1.1  2001/11/14
// First EW checkin
//
// Revision 1.4  2000/03/06
// Revised configuration scheme
//
// Revision 1.3  2000/02/05
// Name change from m8051e to m8051ewarp
//
// Revision 1.2  1999/11/19
// SFR read enable modelling added, corrections to debug testing.
//
// Revision 1.1.1.1  1999/10/28
// "initialization and source check-in for m8051e"
//
//
////////////////////////////////////////////////////////////////////////////////
//
// Purpose      :       Configurable clocked dual-port RAM for modelling
//              :       internal memory used by the M8051W/EW Soft Core.
//
////////////////////////////////////////////////////////////////////////////////

`include "m8051w_tb_cfg.v"

// This module provides the minimum functionality for the M8051EW
// internal data memory.  It is not a general purpose dual port RAM model.

module cram (CSN1, CSN2, RWN1, RWN2, CLK1, CLK2, A1, A2, DI1, DI2, DO1, DO2);
//*******************************************************************       //
//IMPORTANT NOTICE                                                          //
//================                                                          //
//Copyright Mentor Graphics Corporation 1996 - 1999.  All rights reserved.  //
//This file and associated deliverables are the trade secrets,              //
//confidential information and copyrighted works of Mentor Graphics         //
//Corporation and its licensors and are subject to your license agreement   //
//with Mentor Graphics Corporation.                                         //
//                                                                          //
//Use of these deliverables for the purpose of making silicon from an IC    //
//design is limited to the terms and conditions of your license agreement   //
//with Mentor Graphics If you have further questions please contact Mentor  //
//Graphics Customer Support.                                                //
//                                                                          //
//This Mentor Graphics core (m8051w v2002.080) was extracted on             //
//workstation hostid 8316cbec Inventra                                      //

parameter RAM_SIZE = 256;
parameter RAM_AWIDTH = 8;
parameter T_ACCESS = 5;
parameter T_W_PROPN = 5;

output [7:0] DO1,DO2;                       // data out
input  [7:0] DI1,DI2;                       // data in
input  [RAM_AWIDTH-1:0] A1,A2;              // address
input  CSN1, CSN2;                          // active-low chip-select
input  RWN1, RWN2;                          // high for read, low for write
input  CLK1, CLK2;                          // port clocks

reg    [7:0] mem[0:RAM_SIZE-1];  // the memory array
reg    [7:0] DO2;
reg    [7:0] DO1;
integer i;

// Timing inspiration:  TSC6000 DPRAM MN02048008081
//                      Best is 1.95V -40degC strong process
//                      Worst is 1.65V 125degC weak process

// Propagation delays (realistic)
// parameter tar = 1.50:2.32:3.62;

// Propagation delays (pessimistic)
parameter tar = T_ACCESS;

// Timing checks
specify

// RAM Set up and hold time requirements
// specparam tasu = 2.26:4.75:4.75;                            // address set up
specparam tasu = 1.50:1.50:1.50;                               // address set up
specparam tdsu =  0.66:1.82:1.82;                               // data set up
specparam tesu =  0.56:1.45:1.45;                               // enable set up
specparam twsu =  0.60:1.60:1.60;                               // write set up

// Port 1 set up checks
$setup(A1, posedge CLK1, tasu);
$setup(CSN1, posedge CLK1, tesu);
$setup(RWN1, posedge CLK1, twsu);

// Port 2 set up checks
$setup(A2, posedge CLK2, tasu);
$setup(DI2, posedge CLK2, tdsu);
$setup(CSN2, posedge CLK2, tesu);
$setup(RWN2, posedge CLK2, twsu);

// Hold checks - all zero time
$hold(posedge CLK1, A1, 0);
$hold(posedge CLK1, CSN1, 0);
$hold(posedge CLK1, RWN1, 0);
$hold(posedge CLK2, A2, 0);
$hold(posedge CLK2, DI2, 0);
$hold(posedge CLK2, CSN2, 0);
$hold(posedge CLK2, RWN2, 0);

endspecify

// Initialise array for ease of simulation (avoids X-propagation).
initial
  for (i=0; i < `IramSize; i = i +1)
    mem[i] <= 8'h00;

// Register write transfers
always @(posedge CLK2)
  if (~CSN2 && ~RWN2) mem[A2] <= DI2;
  
always @(posedge CLK1)
  if (CLK2 && ~CSN1 && ~CSN2 && ~RWN2 && A1 == A2) begin
    $display("RAM Error:   At time %t, Concurrent read and write accesses occured at the same address %x", $time, A1);
    mem[A1] <= 8'bx;
    DO1 <= #T_ACCESS `BadData;
    end
  else if (~CSN1 && RWN1) begin
    DO1 <= `BadData;
    DO1 <= #T_ACCESS mem[A1];
    end

endmodule
